From 71949e05c47fdce1f90e8515bf733b3a315fae5f Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 21 Apr 2010 01:27:46 +0200 Subject: [PATCH] Refurbish GtkWidgetPath API. The foreach() function is now gone, there's now API to get GTypes and names from the position in the path. --- gtk/gtkcssprovider.c | 115 ++++++++++++++------------ gtk/gtkwidget.c | 4 +- gtk/gtkwidgetpath.c | 191 +++++++++++++++++++++++-------------------- gtk/gtkwidgetpath.h | 32 +++++--- 4 files changed, 185 insertions(+), 157 deletions(-) diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index 8fbddc2431..039f4a0f09 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -271,15 +271,12 @@ struct ComparePathData }; static gboolean -compare_path_foreach (GType type, - const gchar *name, - gpointer user_data) +compare_selector_element (GtkWidgetPath *path, + guint index, + SelectorElement *elem, + guint8 *score) { - ComparePathData *data; - SelectorElement *elem; - - data = user_data; - elem = data->iter->data; + *score = 0; if (elem->elem_type == SELECTOR_TYPE_NAME) { @@ -295,8 +292,7 @@ compare_path_foreach (GType type, /* Type couldn't be resolved, so the selector * clearly doesn't affect the given widget path */ - data->score = 0; - return TRUE; + return FALSE; } elem->elem_type = SELECTOR_GTYPE; @@ -305,84 +301,95 @@ compare_path_foreach (GType type, if (elem->elem_type == SELECTOR_GTYPE) { + GType type; + + type = gtk_widget_path_get_element_type (path, index); + if (!g_type_is_a (type, elem->type)) - { - /* Selector definitely doesn't match */ - if (elem->combinator == COMBINATOR_CHILD) - { - data->score = 0; - return TRUE; - } - else - { - /* Keep checking descendants for a match */ - return FALSE; - } - } - else if (type == elem->type) - data->score |= 0xF; + return FALSE; + + if (type == elem->type) + *score |= 0xF; else { GType parent = type; - guint8 score = 0xE; + + *score = 0xE; while ((parent = g_type_parent (parent)) != G_TYPE_INVALID) { if (parent == elem->type) break; - score--; + *score -= 1; - if (score == 1) + if (*score == 1) { g_warning ("Hierarchy is higher than expected."); break; } } - - data->score |= score; } + + return TRUE; } else if (elem->elem_type == SELECTOR_GLOB) { /* Treat as lowest matching type */ - data->score++; - } - - data->iter = data->iter->next; - - if (data->iter) - { - data->score <<= 4; - return FALSE; + *score = 1; + return TRUE; } - return TRUE; + return FALSE; } static guint64 compare_selector (GtkWidgetPath *path, SelectorPath *selector) { - ComparePathData data; + GSList *elements = selector->elements; + gboolean match = TRUE; + guint64 score = 0; + guint i = 0; + + while (elements && match && + i < gtk_widget_path_length (path)) + { + SelectorElement *elem; + guint8 elem_score; - data.score = 0; - data.path = selector; - data.iter = selector->elements; + elem = elements->data; + elements = elements->next; - gtk_widget_path_foreach (path, - compare_path_foreach, - &data); + match = compare_selector_element (path, i, elem, &elem_score); + i++; - if (data.iter) - { - /* There is remaining data to compare, - * so don't take it as a match. - */ - data.score = 0; + if (!match && elem->combinator == COMBINATOR_DESCENDANT) + { + /* With descendant combinators there may + * be intermediate chidren in the hierarchy + */ + match = TRUE; + } + + if (match) + { + score <<= 4; + score |= elem_score; + } } - return data.score; + /* If there are pending selector + * elements to compare, it's not + * a match. + */ + if (elements) + match = FALSE; + + if (!match) + score = 0; + + return score; } typedef struct StylePriorityInfo StylePriorityInfo; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 3d4d7cc6b7..e4e3e32b86 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -13191,9 +13191,7 @@ gtk_widget_get_path (GtkWidget *widget) while (widget) { - gtk_widget_path_prepend_widget_desc (path, - G_OBJECT_TYPE (widget), - widget->name); + gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (widget)); widget = widget->parent; } diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c index 2af624f557..a6cfcccf32 100644 --- a/gtk/gtkwidgetpath.c +++ b/gtk/gtkwidgetpath.c @@ -34,8 +34,7 @@ struct GtkPathElement struct GtkWidgetPath { - GSList *elems; - GSList *last; /* Last element contains the described widget */ + GArray *elems; /* First element contains the described widget */ }; GtkWidgetPath * @@ -44,139 +43,157 @@ gtk_widget_path_new (void) GtkWidgetPath *path; path = g_slice_new0 (GtkWidgetPath); + path->elems = g_array_new (FALSE, TRUE, sizeof (GtkPathElement)); return path; } -static GtkPathElement * -path_element_new (GType type, - const gchar *name) +GtkWidgetPath * +gtk_widget_path_copy (const GtkWidgetPath *path) { - GtkPathElement *elem; + GtkWidgetPath *new_path; + guint i; - elem = g_slice_new (GtkPathElement); - elem->type = type; - elem->name = g_strdup (name); + g_return_val_if_fail (path != NULL, NULL); - return elem; -} + new_path = gtk_widget_path_new (); -static void -path_element_free (GtkPathElement *elem) -{ - g_free (elem->name); - g_slice_free (GtkPathElement, elem); + for (i = 0; i < path->elems->len; i++) + { + GtkPathElement *elem, new = { 0 }; + + elem = &g_array_index (path->elems, GtkPathElement, i); + + new.type = elem->type; + new.name = g_strdup (elem->name); + + g_array_append_val (new_path->elems, new); + } + + return new_path; } void -gtk_widget_path_prepend_widget_desc (GtkWidgetPath *path, - GType type, - const gchar *name) +gtk_widget_path_free (GtkWidgetPath *path) { + guint i; + g_return_if_fail (path != NULL); - g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET)); - if (!path->elems) + for (i = 0; i < path->elems->len; i++) { - path->elems = g_slist_prepend (NULL, path_element_new (type, name)); - path->last = path->elems; - } - else - { - path->last->next = g_slist_alloc (); - path->last->next->data = path_element_new (type, name); - path->last = path->last->next; + GtkPathElement *elem; + + elem = &g_array_index (path->elems, GtkPathElement, i); + g_free (elem->name); } + + g_array_free (path->elems, TRUE); + g_slice_free (GtkWidgetPath, path); } -GtkWidgetPath * -gtk_widget_path_copy (GtkWidgetPath *path) +guint +gtk_widget_path_length (GtkWidgetPath *path) { - GtkWidgetPath *new_path; - GSList *elems; - - new_path = gtk_widget_path_new (); - elems = path->elems; + g_return_val_if_fail (path != NULL, 0); - while (elems) - { - GtkPathElement *elem; - GSList *link; + return path->elems->len; +} - elem = elems->data; - link = g_slist_alloc (); - link->data = path_element_new (elem->type, elem->name); +guint +gtk_widget_path_prepend_type (GtkWidgetPath *path, + GType type) +{ + GtkPathElement new = { 0 }; - if (!new_path->elems) - new_path->last = new_path->elems = link; - else - { - new_path->last->next = link; - new_path->last = link; - } + g_return_val_if_fail (path != NULL, 0); + g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0); - elems = elems->next; - } + new.type = type; + g_array_append_val (path->elems, new); - return new_path; + return path->elems->len - 1; } -void -gtk_widget_path_free (GtkWidgetPath *path) +GType +gtk_widget_path_get_element_type (GtkWidgetPath *path, + guint pos) { - g_return_if_fail (path != NULL); + GtkPathElement *elem; - g_slist_foreach (path->elems, (GFunc) path_element_free, NULL); - g_slist_free (path->elems); + g_return_val_if_fail (path != NULL, G_TYPE_INVALID); + g_return_val_if_fail (pos < path->elems->len, G_TYPE_INVALID); - g_slice_free (GtkWidgetPath, path); + elem = &g_array_index (path->elems, GtkPathElement, pos); + return elem->type; } -gboolean -gtk_widget_path_has_parent (GtkWidgetPath *path, - GType type) +void +gtk_widget_path_set_element_type (GtkWidgetPath *path, + guint pos, + GType type) { - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE); + GtkPathElement *elem; - GSList *elems = path->elems; + g_return_if_fail (path != NULL); + g_return_if_fail (pos < path->elems->len); + g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET)); - while (elems) - { - GtkPathElement *elem; + elem = &g_array_index (path->elems, GtkPathElement, pos); + elem->type = type; +} - elem = elems->data; +G_CONST_RETURN gchar * +gtk_widget_path_get_element_name (GtkWidgetPath *path, + guint pos) +{ + GtkPathElement *elem; - if (elem->type == type || - g_type_is_a (elem->type, type)) - return TRUE; + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (pos < path->elems->len, NULL); - elems = elems->next; - } - - return FALSE; + elem = &g_array_index (path->elems, GtkPathElement, pos); + return elem->name; } void -gtk_widget_path_foreach (GtkWidgetPath *path, - GtkWidgetPathForeachFunc func, - gpointer user_data) +gtk_widget_path_set_element_name (GtkWidgetPath *path, + guint pos, + const gchar *name) { - GSList *elems; + GtkPathElement *elem; g_return_if_fail (path != NULL); - g_return_if_fail (func != NULL); + g_return_if_fail (pos < path->elems->len); + g_return_if_fail (name != NULL); + + elem = &g_array_index (path->elems, GtkPathElement, pos); + + if (elem->name) + g_free (elem->name); + + elem->name = g_strdup (name); +} + +gboolean +gtk_widget_path_has_parent (const GtkWidgetPath *path, + GType type) +{ + guint i; - elems = path->elems; + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE); - while (elems) + for (i = 1; i < path->elems->len; i++) { GtkPathElement *elem; - elem = elems->data; - elems = elems->next; + elem = &g_array_index (path->elems, GtkPathElement, i); - if ((func) (elem->type, elem->name, user_data)) - return; + if (elem->type == type || + g_type_is_a (elem->type, type)) + return TRUE; } + + return FALSE; } diff --git a/gtk/gtkwidgetpath.h b/gtk/gtkwidgetpath.h index 664562cbc4..3846988fd2 100644 --- a/gtk/gtkwidgetpath.h +++ b/gtk/gtkwidgetpath.h @@ -21,31 +21,37 @@ #define __GTK_WIDGET_PATH_H__ #include +#include "gtkenums.h" G_BEGIN_DECLS typedef struct GtkWidgetPath GtkWidgetPath; -typedef gboolean (* GtkWidgetPathForeachFunc) (GType type, - const gchar *name, - gpointer user_data); GtkWidgetPath * gtk_widget_path_new (void); -void gtk_widget_path_prepend_widget_desc (GtkWidgetPath *path, - GType type, - const gchar *name); +GtkWidgetPath * gtk_widget_path_copy (const GtkWidgetPath *path); +void gtk_widget_path_free (GtkWidgetPath *path); -GtkWidgetPath * gtk_widget_path_copy (GtkWidgetPath *path); -void gtk_widget_path_free (GtkWidgetPath *path); +guint gtk_widget_path_length (GtkWidgetPath *path); -gboolean gtk_widget_path_has_parent (GtkWidgetPath *path, - GType type); +guint gtk_widget_path_prepend_type (GtkWidgetPath *path, + GType type); -void gtk_widget_path_foreach (GtkWidgetPath *path, - GtkWidgetPathForeachFunc func, - gpointer user_data); +GType gtk_widget_path_get_element_type (GtkWidgetPath *path, + guint pos); +void gtk_widget_path_set_element_type (GtkWidgetPath *path, + guint pos, + GType type); +G_CONST_RETURN gchar * gtk_widget_path_get_element_name (GtkWidgetPath *path, + guint pos); +void gtk_widget_path_set_element_name (GtkWidgetPath *path, + guint pos, + const gchar *name); + +gboolean gtk_widget_path_has_parent (const GtkWidgetPath *path, + GType type); G_END_DECLS -- 2.30.2